我正在使用Mockito
和Spy对函数进行单元测试。
这是正在测试的类:
public class RecipeListModelImp
implements RecipeListModelContract {
private Subscription subscription;
private RecipesAPI recipesAPI;
@Inject
public RecipeListModelImp(@NonNull RecipesAPI recipesAPI) {
this.recipesAPI = Preconditions.checkNotNull(recipesAPI);
}
@Override
public void getRecipesFromAPI(final RecipeGetAllListener recipeGetAllListener) {
subscription = recipesAPI.getAllRecipes()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Recipe>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
recipeGetAllListener.onRecipeGetAllFailure(e.getMessage());
}
@Override
public void onNext(List<Recipe> recipe) { recipeGetAllListener.onRecipeGetAllSuccess(recipe);
}
});
}
@Override
public void shutdown() {
if(subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
}
我正在尝试使用Mockito和spy进行测试,因为我不想调用真正的函数recipesAPI。getAllRecipes()
只需验证一下即可。该测试称为testGetRecipesFromAPI()
public class RecipeListModelImpTest {
@Mock Subscription subscription;
@Mock RecipesAPI recipesAPI;
@Mock RecipeListModelContract.RecipeGetAllListener recipeGetAllListener;
private RecipeListModelContract recipeListModel;
@Before
public void setup() {
MockitoAnnotations.initMocks(RecipeListModelImpTest.this);
recipeListModel = new RecipeListModelImp(recipesAPI);
}
@Test
public void testGetRecipesFromAPI() {
RecipeListModelContract recipeListModelSpy = spy(recipeListModel);
RecipesAPI recipeApiSpy = spy(recipesAPI);
doNothing().when(recipeApiSpy).getAllRecipes();
recipeListModelSpy.getRecipesFromAPI(recipeGetAllListener);
verify(recipesAPI, times(1)).getAllRecipes();
}
@Test
public void testShouldShutdown() {
recipeListModel.shutdown();
verify(subscription, times(1)).unsubscribe();
}
}
这是错误:
org.mockito.exceptions.base.MockitoException:
Only void methods can doNothing()!
Example of correct use of doNothing():
doNothing().
doThrow(new RuntimeException())
.when(mock).someVoidMethod();
Above means:
someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called
我也尝试过这样做,它会导致空指针:
@Test
public void testGetRecipesFromAPI() {
RecipeListModelContract recipeListModelSpy = spy(recipeListModel);
RecipesAPI recipeApiSpy = spy(recipesAPI);
doReturn(Observable.just(Subscription.class)).when(recipeApiSpy).getAllRecipes();
recipeListModelSpy.getRecipesFromAPI(recipeGetAllListener);
verify(recipesAPI, times(1)).getAllRecipes();
}
您正在混合间谍(部分模拟)和模拟(完全模拟)。这是不必要的-Spy
允许混合模拟和实际方法调用,但不需要任何部分模拟。在你的情况下,你要么是完全嘲笑,要么不是嘲笑。Mockito的文档中有更多关于模拟和间谍活动的信息。
在第一个示例中,错误是您试图对返回某个内容的方法执行任何操作。莫基托不允许这样。你在第二个例子中所做的几乎是正确的。
对于第二个示例,问题是设置getAllRecipes()
以返回可观察的。只是(Subscription.class)
但是您仍然拥有在测试单元中调用的整个方法链:subscriptbeon
,observeOn
,以及subscripte
。您还需要模拟这些调用,以返回可以使用的模拟对象,或使用抛出NullPointerException的调用。
@Test
public void testGetRecipesFromAPI() {
//recipesAPI.getAllRecipes() needs to be mocked to return something (likely a mock)
// so subscribeOn can be called.
//That needs to be mocked to return something so observeOn can be called
//etc.
recipeListModel.getRecipesFromAPI(recipeGetAllListener);
verify(recipesAPI, times(1)).getAllRecipes();
}
就像你写的
订阅=配方API。getAllRecipes()。subscribeOn(Schedulers.io())
然后方法getAllRecipes()返回一些对象,你不能使用
多诺辛()。当(收到)时。getAllRecipes();
doNothing()-它用于返回void的方法。
变体正确:
doReturn(doReturn(Observable.just(Subscription.class))。当(收到)时。getAllRecipes()
代码中的问题是这一部分:subscribeOn(Schedulers.io())
。如果我们能够消除这一点,那么我们就可以从recipesAPI
返回测试数据,并测试该数据是否由recipeGetAllListener
正确处理。
因此,我们必须以某种方式创建一个seam:如果这是一个生产代码,那么使用调度程序。io()。mainThread()
,如果这是一个测试代码,那么使用一些特定的调度程序。
让我们声明一个接口,它将提供Scheduler
s:
interface SchedulersProvider {
Scheduler getWorkerScheduler();
Scheduler getUiScheduler();
}
现在,让我们使RecipeListModelLimp
依赖于SchedulerProvider
:
public class RecipeListModelImp implements RecipeListModelContract {
...
private SchedulersProvider schedulersProvider;
@Inject
public RecipeListModelImp(@NonNull RecipesAPI recipesAPI,
@NonNull SchedulersProvider schedulerProvider) {
...
this.schedulersProvider = schedulersProvider;
}
...
}
现在,我们将替换调度器:
@Override
public void getRecipesFromAPI(final RecipeGetAllListener recipeGetAllListener) {
subscription = recipesAPI.getAllRecipes()
.subscribeOn(schedulersProvider.getWorkerScheduler())
.observeOn(schedulersProvider.getUiScheduler())
...
}
现在是提供SchedulerProvider的时候了:
@Module
public class MyModule {
...
@Provides public SchedulerProvider provideSchedulerProvider() {
return new SchedulerProvider() {
@Override
Scheduler getWorkerScheduler() {
return Schedulers.io();
}
@Override
Scheduler getUiScheduler() {
return AndroidSchedulers.mainThread();
}
}
}
}
现在让我们创建另一个模块-TestModule
,它将为测试类提供依赖关系。TestModule
将扩展MyModule
并覆盖提供SchedulerProvider
的方法:
public class TestModule extends MyModule {
@Override public SchedulerProvider provideSchedulerProvider() {
return new SchedulerProvider() {
@Override
Scheduler getScheduler() {
return Schedulers.trampoline();
}
@Override
Scheduler getUiScheduler() {
return Schedulers.trampoline();
}
}
}
}
调度程序。trampoline()将在当前线程上执行任务。
现在是创建测试组件的时候了:
@Component(modules = MyModule.class)
public interface TestComponent extends MyComponent {
void inject(RecipeListModelImpTest test);
}
现在在测试课上:
public class RecipeListModelImpTest {
@Mock RecipesAPI recipesAPI;
@Mock RecipeListModelContract.RecipeGetAllListener recipeGetAllListener;
@Inject SchedulerProvider schedulerProvider;
private RecipeListModelContract recipeListModel;
@Before
public void setup() {
TestComponent component = DaggerTestComponent.builder()
.myModule(new TestModule())
.build();
component.inject(this);
MockitoAnnotations.initMocks(this);
recipeListModel = new RecipeListModelImp(recipesAPI, schedulerProvider);
}
...
}
以及实际测试部分:
private static final List<Recipe> TEST_RECIPES = new ArrayList<Recipe>() {
{
add(new Recipe(1)),
add(new Recipe(2))
}
};
@Test
public void testGetRecipesFromAPI() {
when(recipeAPI.getAllRecipes())
.thenReturn(Observable.fromIterable(TEST_RECIPES));
recipeListModel.getRecipesFromAPI(recipeGetAllListener);
// verifying, that `recipeAPI.getAllRecipes()` has been called once
verify(recipeAPI).getAllRecipes();
// verifying, that we received correct result
verify(recipeGetAllListener).onRecipeGetAllSuccess(TEST_RECIPES);
}
问题内容: 有人可以帮我这个忙。我正在使用Jersey休息测试框架版本2.21(在Grizzly容器上)编写Rest资源的单元测试。 当我调试测试类时,看到myManager的模拟对象。但是,当调试进入“ MyResouce类”时,myManager对象将变为null并得到NullPointer异常。 尝试过其他人提供的解决方案,但是没有运气。请有人帮我。我将近三天就遇到这个问题。:( 我的资源类
我有DaoImpl类: 我的测试是: 测试是成功的,但是当我运行具有覆盖率的junit测试时,它显示方法没有被覆盖,因此我的整体单元测试行覆盖率低于要求。我们能涵盖那部分吗?如果是,我们怎么做?谢了。
我正在为我的应用程序创建一个Spring BootAPI。我试图使用mockito对我的服务实现进行单元测试,以模拟出细节。该服务将向数据库添加一个新的构建实体。下面是服务实现和测试实现。楼宇服务: BuildingServiceImpl_UT
如何进行第三个测试来检查异常消息中原因1的存在?我还列出了前两个测试中存在的缺点。首先是不检查消息,其次需要大量样板代码。 我在Mockito中找不到一些有用的东西,但有一些东西看起来是可能的(在语法级别)和功能。 使用catchexception,我创建了这样的测试
问题内容: 我对Node相对较新,并且正在使用knex和书架进行项目。我在对代码进行单元测试时遇到了一些麻烦,但是我不确定自己做错了什么。 基本上,我有一个看起来像这样的模型(称为VorcuProduct): 还有一个函数,如果数据库中不存在VorcuProduct,它将保存它。非常简单。执行此操作的函数如下所示: 哪种方法可以在不影响数据库的情况下进行测试?我是否需要模拟以返回模型或未定义模型(
我使用JUnit4和Mockito创建了一个Spring Boot2应用程序。当我测试某种方法时。会出现这样的例外: 这是我的测试代码 SuveryService.java SurveyRepository.java 我引用了这篇文章Mockito NullPointerException,但这个问题仍然存在。任何帮助都将被应用。