我有一些代码如下所示:
-module(ca_data).
-export([delete_ca_data/1]).
% ...
delete_ca_data(N) when N < 1 -> ?NEGATIVE_ID_ERROR;
delete_ca_data(N) -> util_db_generic:delete_object(ca_data, N, fun(_) -> ok end).
% ...我有一些测试代码,如下所示:
wrap_meck(MockMod, MockArgs, F) ->
meck:new(MockMod, MockArgs),
try
F()
catch Ex ->
throw(Ex)
after
meck:unload(MockMod)
end.
delete_ca_data_test() ->
F = fun() ->
meck:expect(util_db_generic, delete_object, fun (_, _, _) -> ok end),
?assertEqual(?NEGATIVE_ID_ERROR, ca_data:delete_ca_data(-1)),
?assertEqual([], meck:history(util_db_generic)),
meck:expect(util_db_generic, delete_object, fun(_, _, _) -> ok end),
?assertEqual(ok, ca_data:delete_ca_data(1)),
?assertEqual(
[{self(), {util_db_generic, delete_object, [ca_data, 1, fun(_) -> ok end]}, ok}], % Uh-oh
meck:history(util_db_generic)
)
end,
wrap_meck(util_db_generic, [], F).不幸的是,util_db_generic:delete_object函数是通过在测试模块中创建的函数调用的。
这提供了一些问题,当试图断言函数调用的历史记录时(例如,在标记为“Uh-oh”的行上)。因为这个函数是在原地创建的(而且内存指针实际上是随机的),所以断言这个函数应该是什么样子是很困难的。此代码不会导致任何编译错误。但是,断言永远不会返回为有效的,因为有两个不同的函数相互声明(一个在ca_data模块中创建,一个在测试用例中创建)。我尝试使用?assertMatch并将fun(_) -> ok end的out更改为_,但我在assert行上得到了这个编译错误:
illegal pattern如何才能与这些结果相匹配?
发布于 2022-04-30 10:57:52
您想要的断言可能如下所示:
?assertMatch(
[{Self, {util_db_generic, delete_object, [ca_data, 1, Fun]}, ok}] when Self == self() andalso is_function(Fun, 1), % Yay?
meck:history(util_db_generic)
)这与?assertMatch文档相匹配,因为您将在这样的case语句中编写相同的内容:
case meck:history(util_db_generic) of
[{Self, {util_db_generic, delete_object, [ca_data, 1, Fun]}, ok}] when Self == self() andalso is_function(Fun, 1) ->
true;
_ ->
false
end(注意,case语句在警卫之间使用,时可能会更短,但在宏中不起作用,所以这里我们必须使用andalso )。
您必须首先将pid与Self匹配,然后在一个保护程序中检查它的原因是匹配表达式中不允许函数调用:
1> [self()] = [self()].
* 1:2: illegal pattern因此,您必须先绑定它,然后检查保护中的值。当然,如果您上面所写的,在表达式外绑定Self也是有效的。这只是一个品味和/或可读性的问题(事实上,我认为绑定Self首先更清楚)。
发布于 2022-04-29 20:37:49
虽然Erlang文档通常很好,但这一点让用户失望。The assertMatch documentation states
Evaluates Expr and matches the result against GuardedPattern, if testing is enabled. ... GuardedPattern can be anything that you can write on the left hand side of the -> symbol in a case-clause, except that it cannot contain comma-separated guard tests.And the documentation for self() states
Allowed in guard tests.但是,self()函数不能用于assertMatch宏。我不清楚为什么,但实验已经证明了这一点。
编辑1:
情节更复杂了!当我编辑测试代码时,如下所示:
delete_ca_data_test() ->
F = fun() ->
meck:expect(util_db_generic, delete_object, fun (_, _, _) -> ok end),
?assertEqual(?NEGATIVE_ID_ERROR, ca_data:delete_ca_data(-1)),
?assertEqual([], meck:history(util_db_generic)),
meck:expect(util_db_generic, delete_object, fun(_, _, _) -> ok end),
?assertEqual(ok, ca_data:delete_ca_data(1)),
Self = self(),
?assertEqual(
[{Self, {util_db_generic, delete_object, [ca_data, 1, _]}, ok}], % Uh-oh
meck:history(util_db_generic)
)
end,
wrap_meck(util_db_generic, [], F).代码编译并正确运行!对我来说,这是一个令人惊讶的结果!函数(应该可以在警卫中使用)是不允许的,但是函数的返回是!有意思的!
https://stackoverflow.com/questions/72063449
复制相似问题