Flutter测试使用Mockito – 当注册存根的API不起作用时

huangapple go评论56阅读模式
英文:

Flutter test using Mockito - when API for register stub doesn't work

问题

我发表这个问题是因为这种行为对我来说非常奇怪!我不是Mockito的专家,所以这可能只是我的错误。

@GenerateMocks([AuthProvider])
void main() {
  test('If there is not a valid session, the data are clean', () async {
    UserDataProvider provider = UserDataProvider();
    MockAuthProvider mock = MockAuthProvider();

    when(mock.isLoggedIn).thenReturn(false);

    await provider.update(MockAuthProvider());
    expect((await provider.joinedCommunities).isEmpty, true);
  });
}

抛出了一个异常

package:mockito/src/mock.dart 191:7                      Mock._noSuchMethod
package:mockito/src/mock.dart 185:45                     Mock.noSuchMethod
test/provider/user_data_provider_test.mocks.dart 59:33   MockAuthProvider.isLoggedIn
package:unimeet/providers/user_data_provider.dart 22:22  UserDataProvider.update
test/provider/user_data_provider_test.dart 17:20         main.<fn>

MissingStubError: 'isLoggedIn'
No stub was found which matches the arguments of this method call:
isLoggedIn

Add a stub for this method using Mockito's 'when' API, or generate the MockAuthProvider mock with the @GenerateNiceMocks annotation (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html).

正如您所看到的,我试图为一个简单的getter注册返回值,但却抛出了异常。

请告诉我,谢谢。

英文:

I'm posting this question because this behavior seems very strange to me!
I ain't an expert on mockito, so this may be only my error.

@GenerateMocks([AuthProvider])
void main() {
  test(&#39;If there is not a valid session, the data are clean&#39;, () async {
    UserDataProvider provider = UserDataProvider();
    MockAuthProvider mock = MockAuthProvider();

    when(mock.isLoggedIn).thenReturn(false);

    await provider.update(MockAuthProvider());
    expect((await provider.joinedCommunities).isEmpty, true);
  });
}

An exception is thrown

package:mockito/src/mock.dart 191:7                      Mock._noSuchMethod
package:mockito/src/mock.dart 185:45                     Mock.noSuchMethod
test/provider/user_data_provider_test.mocks.dart 59:33   MockAuthProvider.isLoggedIn
package:unimeet/providers/user_data_provider.dart 22:22  UserDataProvider.update
test/provider/user_data_provider_test.dart 17:20         main.&lt;fn&gt;

MissingStubError: &#39;isLoggedIn&#39;
No stub was found which matches the arguments of this method call:
isLoggedIn

Add a stub for this method using Mockito&#39;s &#39;when&#39; API, or generate the MockAuthProvider mock with the @GenerateNiceMocks annotation (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html).

As you can see I'm trying to register a return value for a simple getter but an exception is thrown.

Let me know and thank you

答案1

得分: 1

你正在添加一个用于 isLoggedIn 字段/获取器的存根:

when(mock.isLoggedIn).thenReturn(false);

但在接下来的一行中,你使用你的模拟对象的全新实例来调用 provider.update,而不是你存根的那个实例。一个空实例。

解决方案非常简单。只需将构造新实例的部分替换为已经存根的实例,就像这样:

@GenerateMocks([AuthProvider])
void main() {
  test('If there is not a valid session, the data are clean', () async {
    final provider = UserDataProvider();
    final mock = MockAuthProvider();

    when(mock.isLoggedIn).thenReturn(false);

    await provider.update(mock);
    expect((await provider.joinedCommunities).isEmpty, true);
  });
}

我还将变量的定义从左侧使用类型更改为 final 关键字,因为在这里使用类型是多余的 - 你已经在右侧的代码中显示了类型给开发人员。在左侧只使用类型,将其标记为 var,一个可变的变量。默认情况下,将变量定义为 final,除非确实需要对其进行更改。作为一个经验法则。你仍然可以在 final 中改变对象(比如对 List 使用 add()),只是不能重新定义变量本身。

如果你永远不打算更改一个变量,请使用 finalconst,可以替代 var 或附加到类型。一个 final 变量只能设置一次;一个 const 变量是编译时常数。 (const 变量在隐式情况下也是 final。)

英文:

What is happening, is you are indeed adding a stub for the mentioned isLoggedIn field/getter:

when(mock.isLoggedIn).thenReturn(false);

but in the next line, you are calling provider.update with a brand new instance of your mock. Not the one that you stubbed. An empty one.

The solution is really easy. Simply replace constructing a new instance with your already stubbed instance, like this:

@GenerateMocks([AuthProvider])
void main() {
  test(&#39;If there is not a valid session, the data are clean&#39;, () async {
    final provider = UserDataProvider();
    final mock = MockAuthProvider();

    when(mock.isLoggedIn).thenReturn(false);

    await provider.update(mock);
    expect((await provider.joinedCommunities).isEmpty, true);
  });
}

I also changed the definitions of the variables from using type on the left-hand side to a final keyword, because type is redundant here - you are already showing the type to the developer that reads the code on the right-hand side. By using only a type on the left side, you mark it as a var, a mutable variable. Use final as a default for your variables, except for cases where you indeed want to mutate it. As a rule of thumb. You still can mutate the object (like add() to a List) in a final. Just not redefine the variable itself.

> If you never intend to change a variable, use final or const, either instead of var or in addition to a type. A final variable can be set only once; a const variable is a compile-time constant. (Const variables are implicitly final.)

huangapple
  • 本文由 发表于 2023年3月4日 02:26:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75630643.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定