简体   繁体   English

如何将 Mock 设置为具有默认行为并可以在某些测试中覆盖它

[英]How to set Mock to have a default behavior and can override it in some test

I want to mock a dependency and return a default value in most test cases since most of them should not care about the values returned but there are some certain cases like I would like to test like the dependency returns some weird values or just throw.我想在大多数测试用例中模拟一个依赖项并返回一个默认值,因为他们中的大多数人不应该关心返回的值,但是在某些特定情况下,我想测试依赖项返回一些奇怪的值或者只是抛出。 So I am modeling it in this way.所以我以这种方式对其进行建模。 Most cases, it should return a nice and valid value.大多数情况下,它应该返回一个不错且有效的值。

Test Setup which return the 20L by default for all test classes.默认情况下为所有测试类返回20L的测试设置。

Dependency dependency = Mockito.mock(Dependency.class);
when(dependency.returnSomeVal()).thenReturn(20L);

In a specific test cases class, I would like to override the behavior like below:在特定的测试用例 class 中,我想覆盖如下行为:

when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases

But I don't find a good solution to override the existing behavior?但是我没有找到一个很好的解决方案来覆盖现有的行为? Any idea?任何想法?

You can reset the mock and add behavior.您可以重置模拟并添加行为。 In the test, do在测试中,做

Mockito.reset(dependency);
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases

Resetting will remove all mocked behavior on this class though.不过,重置将删除此 class 上的所有模拟行为。 If you want to remock only some methods, then you have to create the mock from scratch.如果您只想重新模拟某些方法,那么您必须从头开始创建模拟。

I ended using myself this pattern to mock a bunch of methods of a class providing configurations.我结束了自己使用这种模式来模拟提供配置的 class 的一堆方法。

In a @Before method I setup a bunch of stubs for a mocked object that provide a correct configuration for each test.@Before方法中,我为模拟的 object 设置了一堆存根,为每个测试提供正确的配置。 Afterwards, in each test it was extremely convenient to only override one of those stubs to provide a different configuration and test a different error case.之后,在每个测试中,仅覆盖其中一个存根以提供不同的配置并测试不同的错误情况非常方便。

I think the response from Hari Menon is correct but it somehow defeats the purpose explained in the question.我认为 Hari Menon 的回答是正确的,但它在某种程度上违背了问题中解释的目的。 If the mock is reset, all the stubs would need to be added again, making this pattern very confusing (it would be better to not use any overriding than using reset in this case, the code would be way more straightforward).如果重置了模拟,则需要再次添加所有存根,从而使这种模式非常混乱(在这种情况下,最好不要使用任何覆盖而不是使用重置,代码会更直接)。

The comments added to the question provide indeed an indirect answer on how to achieve this, and why it works, but it took me a bit to get it working.添加到问题中的评论确实提供了关于如何实现这一点以及它为什么起作用的间接答案,但我花了一点时间才让它起作用。

In spite of one of the comments, I made everything work by using in my @Before fixture when().thenReturn() and overriding the concrete stub with doReturn().when()尽管有评论之一,我还是通过在我的 @Before 夹具中使用 when().thenReturn() 并用 doReturn().when() 覆盖具体存根,使一切正常工作

Example:例子:

public class WorkerTest {

    private ConfigProvider mockedConfigProvider = mock(ConfigProvider.class);

    @Before
    public void setup() {
    // Setup stubs with a correct config
        when(mockedConfigProvider.getValue("property1")).thenReturn("value1");
        when(mockedConfigProvider.getValue("property2")).thenReturn("value2");
        when(mockedConfigProvider.getValue("property3")).thenReturn("value3");
        when(mockedConfigProvider.getValue("property4")).thenReturn("value4");
    }

    @Test
    public void test_GoodConfig(){
        // The config object gets injected in the test worker
        Worker testWorker = new Worker(mockedConfigProvider);
        // testWorker.execute() returns true if everything went well
        assertTrue(testWorker.execute());
    }

    @Test
    public void test_BadConfigProp1(){
        // Test now with a broken 'property1', overriding that stub.
        doReturn(null).when(mockedConfigProvider).getValue("property1");
        Worker testWorker = new Worker(mockedConfigProvider);
        // testWorker.execute() returns false if there is a problem.
        assertFalse(testWorker.execute());
    }

    @Test
    public void test_BadConfigProp2(){
    // This test needs to only override the result of property2
    doReturn("crazy result").when(mockedConfigProvider).getValue("property2");
    ...

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM