在测试之间重用时,Mockito mock doAnswer返回相同的值

时间:2018-01-16 16:28:53

标签: java mockito

我有以下测试。当我单独运行它们时,它们会通过。如果我只运行第一次通过所有这些。

Business Logic从APIServiceTask代码获取JSON响应。它创建一个使用EventBus发布的事件。我正在编写测试来验证EventBus是否正在创建正确的调用。

最后的JSON Reponses类只是我想要发布的答案。如果我运行所有测试,似乎loginFailureChangePasswordJSON是发布到业务逻辑的那个。

public class LoginBusinessLogic {
    private static LoginBusinessLogic instance = null;
    APIServiceTask apiServiceTask;

    public static LoginBusinessLogic getInstance(APIServiceTask apiServiceTask) {
        if (instance == null) {
            instance = new LoginBusinessLogic();
            instance.apiServiceTask = apiServiceTask;
        }
        return instance;
    }

    protected void doLogin() {
        EventBus.getDefault().register(this);
        apiServiceTask.execute();
    }

    @Subscribe
    public void onEvent(ServiceResultEvent event) {
        switch (event.event) {
            case failed:
                handleLoginError(event.result);
                break;
            case cancelled:
                EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_CANCELLE, event.result));
                break;
            case error:
                if(event.originatorEvent != LoginEvent.TYPE_TOUCH_TOKEN_DELETE) {
                    EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_ERROR, event.result));
                }
                break;
            default:
                break;
        }
        EventBus.getDefault().unregister(this);
    }

    private void handleLoginError(String error) {
        ErrorModel signInError = new Gson().fromJson(error, ErrorModel.class);
        int statusCode = signInError.getMTBStatusCode();
        String errMsg;
        if (statusCode == 40022) {
            errMsg = signInError.getUserMessage();
        } else {
            errMsg = signInError.getUserMessage().replace("*", "").replace("\"", "");
        }
        if (statusCode == 40001) {
            EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_FAILED, statusCode, errMsg, false, false));
        } else if (statusCode == 40108) {
            EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_FAILED, statusCode, errMsg, true, false));
        }
        else if (statusCode == 40107) {
            EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_FAILED, statusCode, errMsg, false, false));
        } else if (statusCode == 40104) {
            EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_FAILED, statusCode, errMsg, false, true));
        } else {
            EventBus.getDefault().postSticky(new LoginEvent(LoginEvent.TYPE_FAILED, statusCode, errMsg, false, false));
        }
    }
}

public class APIServiceTask {
    public APIServiceTask(){
    }

    @SuppressWarnings("ConstantConditions")
    public void execute() {

    }
}

public class BusinessLogicTests {
    @Mock
    APIServiceTask service;

    private LoginEvent loginEvent;
    private LoginBusinessLogic loginBusinessLogic;

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

        loginBusinessLogic = LoginBusinessLogic.getInstance(service);

        EventBus.getDefault().register(this);
    }

    @After
    public void tearDown(){
        EventBus.getDefault().unregister(this);
    }

    @Subscribe
    public void onEvent(LoginEvent event){
        loginEvent = event;
    }

    @Test
    public void badUsernamePasscode(){
        doAnswer(JSONResponses.loginInvalidUsernamePasscodeJSON())
                .when(service).execute();

        loginBusinessLogic.doLogin();
        Assert.assertEquals(40108, loginEvent.mtbStstusCode);
    }

    @Test
    public void accountBlocked(){
        doAnswer(JSONResponses.loginAccountBlockedJSON())
                .when(service).execute();

        loginBusinessLogic.doLogin();
        Assert.assertEquals(40104, loginEvent.mtbStstusCode);
    }

    @Test
    public void temporaryPasscode(){
        doAnswer(JSONResponses.loginTemporaryPasscodeJSON())
                .when(service).execute();

        loginBusinessLogic.doLogin();
        Assert.assertEquals(40109, loginEvent.mtbStstusCode);
    }

    @Test
    public void changedPasscode(){
        doAnswer(JSONResponses.loginFailureChangePasscodeJSON())
                .when(service).execute();

        loginBusinessLogic.doLogin();
        Assert.assertEquals(40107, loginEvent.mtbStstusCode);
    }
}

public class JSONResponses {
    public static Answer loginFailureChangePasscodeJSON(){
        Answer answer = new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                String result = "{\"MTBStatusCode\":40107, \"UserMessage\":\"Your passcode has changed since last login.\"}";
                EventBus.getDefault().post(new ServiceResultEvent(ServiceResultEvent.EVENT_TYPE.failed, result, 0));
                return null;
            }
        };

        return answer;
    }

    public static Answer loginAccountBlockedJSON(){
        Answer answer = new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                String result = "{\"Version\":1,\"MTBStatusCode\":40104,\"HttpStatus\":401,\"UserMessage\":\"\\\"Your account is locked due to too many failed login attempts. <br><br><a href=\\\"https://onlinebanking.mtb.com/login/passcodereset\\\">Reset Passcode ></a>\\\"\",\"DeveloperMessage\":\"\\\"Account locked via multi-factor authentication.\\\"\"}";

                EventBus.getDefault().post(new ServiceResultEvent(ServiceResultEvent.EVENT_TYPE.failed, result, 0));
                return null;
            }
        };

        return answer;
    }

    public static Answer loginInvalidUsernamePasscodeJSON(){
        Answer answer = new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                String result = "{\"Version\":1,\"MTBStatusCode\":40108,\"HttpStatus\":401,\"UserMessage\":\"\\\"User ID or Passcode doesn’t match. Try again.\\\"\",\"DeveloperMessage\":\"\\\"Voyager Error -1073739414 : User ID or Passcode doesn’t match. Try again.\\\"\"}";

                EventBus.getDefault().post(new ServiceResultEvent(ServiceResultEvent.EVENT_TYPE.failed, result, 0));
                return null;
            }
        };

        return answer;
    }

    public static Answer loginTemporaryPasscodeJSON(){
        Answer answer = new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                String result = "{\"Version\":1,\"MTBStatusCode\":40107,\"HttpStatus\":401,\"UserMessage\":\"\\\"You have logged in with a temporary passcode. Log in to <a href=\\\"http://mtb.com/olb-login\\\">M&T Online Banking</a> to create a new passcode.\\\"\",\"DeveloperMessage\":\"\\\"Password should be changed.\\\"\"}";

                EventBus.getDefault().post(new ServiceResultEvent(ServiceResultEvent.EVENT_TYPE.failed, result, 0));
                return null;
            }
        };

        return answer;
    }
}

1 个答案:

答案 0 :(得分:0)

对于任何感兴趣的人来说,当其他测试运行时,单身人士似乎仍然存在。我发现修复它的两种方法是在单独的方法中清空单例,或者在LoginBusinessLogic中将if语句移到if之外。

instance.apiServiceTask = apiServiceTask;