在单元测试中模拟时发出的问题

时间:2019-04-16 05:51:19

标签: junit mockito

我在为junit测试嘲笑事物时遇到了一个问题。

场景如下:

A类通过第三方jar实现一个接口,并且需要实现method1。 除method1之外,A还包含method2,该方法从method1调用。 method2本身会调用一些外部服务。

我想对方法1进行单元测试。

方法1接受输入,例如X。X内包装了一个输入变量,例如var1。方法1中的逻辑使用var1,方法1在X中设置另一个变量,例如var2。

因此,我首先模拟了类A,以便模拟method2。

template<typename T, bool noexcept_state = true>
struct make_noexcept { using type = T; };

template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) noexcept, noexcept_state> { using type = R(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const noexcept, noexcept_state> { using type = R(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile noexcept, noexcept_state> { using type = R(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile noexcept, noexcept_state> { using type = R(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) noexcept, noexcept_state> { using type = R(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const noexcept, noexcept_state> { using type = R(Args..., ...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile noexcept, noexcept_state> { using type = R(Args..., ...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile noexcept, noexcept_state> { using type = R(Args..., ...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) & noexcept, noexcept_state> { using type = R(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const & noexcept, noexcept_state> { using type = R(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile & noexcept, noexcept_state> { using type = R(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile & noexcept, noexcept_state> { using type = R(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) & noexcept, noexcept_state> { using type = R(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const & noexcept, noexcept_state> { using type = R(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile & noexcept, noexcept_state> { using type = R(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile & noexcept, noexcept_state> { using type = R(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) && noexcept, noexcept_state> { using type = R(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const && noexcept, noexcept_state> { using type = R(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile && noexcept, noexcept_state> { using type = R(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile && noexcept, noexcept_state> { using type = R(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) && noexcept, noexcept_state> { using type = R(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const && noexcept, noexcept_state> { using type = R(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile && noexcept, noexcept_state> { using type = R(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile && noexcept, noexcept_state> { using type = R(Args..., ...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) noexcept, noexcept_state> { using type = R(C::*)(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const noexcept, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const noexcept, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) & noexcept, noexcept_state> { using type = R(C::*)(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const & noexcept, noexcept_state> { using type = R(C::*)(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile & noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile & noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile & noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) && noexcept, noexcept_state> { using type = R(C::*)(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const && noexcept, noexcept_state> { using type = R(C::*)(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile && noexcept, noexcept_state> { using type = R(C::*)(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile && noexcept, noexcept_state> { using type = R(C::*)(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile && noexcept, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile && noexcept(noexcept_state); };

// MSVC++ 2019 (v142) doesn't allow `noexcept(x)` with a template parameter `x` in the template specialization list.
// (e.g., `struct make_noexcept<R(Args...) noexcept(noexcept_state)>` gives - C2057: expected constant expression)
// GCC 7.1.0 and Clang 5.0.0 (and later versions) were tested and do allow this, so MSVC++ is probably wrong.
// $ g++ prog.cc -Wall -Wextra -std=c++17 -pedantic
// $ clang++ prog.cc -Wall -Wextra -std=c++17 -pedantic

template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...), noexcept_state> { using type = R(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const, noexcept_state> { using type = R(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile, noexcept_state> { using type = R(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile, noexcept_state> { using type = R(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...), noexcept_state> { using type = R(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const, noexcept_state> { using type = R(Args..., ...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile, noexcept_state> { using type = R(Args..., ...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile, noexcept_state> { using type = R(Args..., ...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...)&, noexcept_state> { using type = R(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const &, noexcept_state> { using type = R(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile &, noexcept_state> { using type = R(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile &, noexcept_state> { using type = R(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...)&, noexcept_state> { using type = R(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const &, noexcept_state> { using type = R(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile &, noexcept_state> { using type = R(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile &, noexcept_state> { using type = R(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) &&, noexcept_state> { using type = R(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const &&, noexcept_state> { using type = R(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) volatile &&, noexcept_state> { using type = R(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args...) const volatile &&, noexcept_state> { using type = R(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) &&, noexcept_state> { using type = R(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const &&, noexcept_state> { using type = R(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) volatile &&, noexcept_state> { using type = R(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename... Args>
struct make_noexcept<R(Args..., ...) const volatile &&, noexcept_state> { using type = R(Args..., ...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...), noexcept_state> { using type = R(C::*)(Args...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...), noexcept_state> { using type = R(C::*)(Args..., ...) noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const, noexcept_state> { using type = R(C::*)(Args...) const noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile, noexcept_state> { using type = R(C::*)(Args...) volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile, noexcept_state> { using type = R(C::*)(Args...) const volatile noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...)&, noexcept_state> { using type = R(C::*)(Args...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const &, noexcept_state> { using type = R(C::*)(Args...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile &, noexcept_state> { using type = R(C::*)(Args...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile &, noexcept_state> { using type = R(C::*)(Args...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...)&, noexcept_state> { using type = R(C::*)(Args..., ...) & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const &, noexcept_state> { using type = R(C::*)(Args..., ...) const & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile &, noexcept_state> { using type = R(C::*)(Args..., ...) volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile &, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile & noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) &&, noexcept_state> { using type = R(C::*)(Args...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const &&, noexcept_state> { using type = R(C::*)(Args...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) volatile &&, noexcept_state> { using type = R(C::*)(Args...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args...) const volatile &&, noexcept_state> { using type = R(C::*)(Args...) const volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) &&, noexcept_state> { using type = R(C::*)(Args..., ...) && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const &&, noexcept_state> { using type = R(C::*)(Args..., ...) const && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) volatile &&, noexcept_state> { using type = R(C::*)(Args..., ...) volatile && noexcept(noexcept_state); };
template<bool noexcept_state, typename R, typename C, typename... Args>
struct make_noexcept<R(C::*)(Args..., ...) const volatile &&, noexcept_state> { using type = R(C::*)(Args..., ...) const volatile && noexcept(noexcept_state); };

template<typename T, bool noexcept_state = true>
using make_noexcept_t = typename make_noexcept<T, noexcept_state>::type;

template<typename T>
using remove_noexcept_t = make_noexcept_t<T, false>;

然后,我还必须模拟X来设置var1。

A a= Mockito.spy(new A());
doReturn("some dummy value").when(a).method2();

最后:

X x= mock(X.class);
when(x.getVariable("var1")).thenReturn("some dummy value for var1");

在方法1中,我这样做:

a.method1(x);

现在在单元测试中,当我尝试从x获取var2时,我得到了空值。

x.setVariable("var2","some value for var2").

我希望“ var2有一定的价值”,但我会得到null。

1 个答案:

答案 0 :(得分:1)

您正确地是部分模拟类A,但是对类X使用了模拟。

您对x.getVariable("var2")没有期望,因此它总是返回null。 在模拟电话上呼叫x.setVariable("var2","some value for var2").对此呼叫没有影响

我的建议:

  1. 如果可能的话,只使用实数X而不是模拟
  2. 或者,您也可以部分模拟X
X x = mock(X.class);
when(x.getVariable("var2")).thenCallRealMethod();
doCallRealMethod().when(x).setVariable(anyString(), anyString());
when(x.getVariable("var1")).thenReturn("some dummy value for var1");

另外,如果被测试的方法method1在其主体中未调用method2,请使用A的真实实例代替局部模拟