简体   繁体   English

被单元测试和Mockito混淆

[英]confused by unit testing and Mockito

I'm new to unit test and Mockito. 我是单元测试和Mockito的新手。 I got confused by what I should test and verify. 我对应该测试和验证的内容感到困惑。 I have a class A as follows: 我的A类课程如下:

public class A{
    @Autowired
    private B b;

    public double doSomething(Request r){
        r = b.process1(r);
        r = b.process2(r);
        return calculateFinal(r);
    }

    public void reportSomething(Request r){
        r = b.process1(r);
        r = b.process2(r);
        b.report(r);
    }

    private int calculateFinal(Request r){
        return r.getFinalScore() * 2;
    }
}

Suppose I want to test these two methods with Junit test. 假设我想用Junit测试来测试这两种方法。 Since I have a dependency B in A, I mock it with Mockito. 因为我在A中有一个依赖项B,所以我用Mockito对其进行了模拟。 For both tests, I was told that I should assume that the dependency b is fully tested and properly working since we want to test the business logic in A. 对于这两个测试,我都被告知我应该假设依赖项b已经过充分测试并且可以正常工作,因为我们要测试A中的业务逻辑。

At first it looks like that I don't have to test anything for reportSomething() since it only involves calls to b and they are all "working"? reportSomething()来,我不需要为reportSomething()测试任何东西,因为它仅涉及对b调用,并且它们都在“正常工作”? The only thing I can think of to test is whether they are actually called and the order of the calls, correct? 我唯一想测试的是它们是否真正被调用以及调用的顺序正确吗? So should I just call a.reportSomething() and then do the verification? 那么我应该只调用a.reportSomething()然后进行验证吗? One thing that bugs me is that whether I should stub the b.process1() and b.process2() to return anything. 让我感到困扰的一件事是,是否应该对b.process1()和b.process2()进行存根以返回任何内容。 I tried without stubbing anything and it worked, but why? 我试着不存anything任何东西,它奏效了,但是为什么呢?

For testDoSomething(), I think what I'm really testing is the calculateFinal() method. 对于testDoSomething(),我认为我真正测试的是calculateFinal()方法。 But since it uses the data from the Request object, I need to set that data in Request r first. 但是由于它使用了Request对象中的数据,因此我需要先在Request r设置该数据。 Since r directly comes from b.process2() , I should stub the method call to return a Request object with that data. 由于r直接来自b.process2() ,所以我应该对方法调用进行存根处理以返回带有该数据的Request对象。 But I could skip the stubbing of b.process1() , right? 但是我可以跳过b.process1()的存根,对吗?

Is this a right thinking process? 这是正确的思考过程吗? Did I miss something or misunderstand something? 我错过了什么还是误会了吗? If it's right, is there a better and cleaner way to write it? 如果是正确的话,有没有更好,更干净的方法来编写它? Thank you! 谢谢!

public class ATest{
    private static final int SCORE = 100;

    @Mock
    private B mockB;

    @InjectMocks
    private A aClient;

    @Before
    public void setUpTest{
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testReportSomething(){
        // what should I test here?

        Request r = new Request();

        // is it necessary to include the following two lines?
        when(mockB.process1(any(Request.class))).return(r);
        when(mockB.process2(any(Request.class))).return(r);


        aClient.reportSomething(r);
        InOrder inOrder = inOrder(mockProcesser);
        inOrder.verify(mockProcesser).process1(any(Request.class));
        inOrder.verify(mockProcesser).process2(any(Request.class));
        inOrder.verify(mockProcesser).report(any(Request.class));
    }

    @Test
    public void testDoSomething(){
        // Is this correct?
        Request r = new Request();
        r.setFinal(SCORE);

        // I skipped this line and it still works
        when(mockB.process1(any(Request.class))).return(r);

        when(mockB.process2(any(Request.class))).return(r);
        assert(SCORE * 2, aClient.doSomething(r));
        // is it still necessary to verify the call to mockB?
    }
}

You are doing your test incorrectly. 您的测试不正确。 Let's look at the method you want to test: 让我们看一下您要测试的方法:

public void reportSomething(Request r){
    r = b.process1(r);
    r = b.process2(r);
    b.report(r);
}

First of all, you need to mock that when b processes a request, it returns the expected result; 首先,您需要嘲笑b处理请求时,它会返回预期结果; DO NOT therefore use the same return value for two invocations. 因此,请勿对两个调用使用相同的返回值。

Here is how I would write the test: 这是我编写测试的方式:

final Request r = mock(Request.class);
final Request r1 = mock(Request.class);
final Request r2 = mock(Request.class);

when(mockB.process1(r)).thenReturn(r1);
when(mockB.process2(r1)).thenReturn(r2);
doNothing().when(mockB).report(any(Request.class));

final InOrder inOrder = inOrder(mockB);

// Launch... And then verify:

inOrder.verify(mockB).process1(r);
inOrder.verify(mockB).process2(r1);
inOrder.verify(mockB).report(r2);
inOrder.verifyNoMoreInteractions();

As to: 关于:

  // is it necessary to include the following two lines? 

Yes. 是。 By default, when unspecified, a mocked instance will return Java's defaults: 0 for numeric primitives, false for boolean, null for objects. 默认情况下,未指定时,模拟实例将返回Java的默认值:数字基元为0,布尔值为false,对象为null。 You MUST specify what you want to be returned by stubbing. 您必须指定要通过存根返回的内容。

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

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