سؤال

I am using Typemock for some of my unit tests. I have mocked static class Widget. I want to mock the return of Widget.GetPrice(123) to return value A.

Isolate.Fake.StaticMethods<Widget>();
Isolate.WhenCalled(() => Widget.GetPrice(123)).WillReturn("A");

I also want to verify that Widget.GetPrice(456) was NOT called.

Isolate.Verify.WasNotCalled(() => Widget.GetPrice(456));

It seems that WasNotCalled does not take parameters into consideration. The test comes back saying that it failed b/c Widget.GetPrice was in fact called.

The only way I could think to do this is to do a DoInstead call and increment a counter when Widget.GetPrice(456) is called. The end of the test would check if the counter was incremented. Is there a better way to do this though?

هل كانت مفيدة؟

المحلول

There are a couple of ways you can do this.

First, your DoInstead idea is pretty good, but I would tweak it to contain an assertion:

Isolate.WhenCalled(() => Widget.GetPrice(0)).DoInstead(
  context =>
  {
    var num = (int)context.Parameters[0];
    Assert.AreNotEqual(456, num);
    return "A";
  });

The idea there is that when the method is called, you verify at the time of the call that the incoming parameter is what you expect and fail the test with the Assert statement if it's not.

(You'll also note I put "0" in as the parameter because, as you noticed, the actual value doesn't matter. I find it's easier for future maintenance to use null/0/etc when the parameters don't matter so you don't "forget" or "get fooled" into thinking that it does matter.)

The second thing you could do is use WithExactArguments to control the behavior.

// Provide some default behavior that will break things
// if the wrong value comes in.
Isolate
  .WhenCalled(() => Widget.GetPrice(0))
  .WillThrow(new InvalidOperationException());

// Now specify the right behavior if the arguments match.
Isolate
  .WhenCalled(() => Widget.GetPrice(123))
  .WithExactArguments()
  .WillReturn("A");

The "WithExactArguments" will make your behavior run only if the arguments match. When you run your test, if an invalid value gets passed in, the exception will get thrown and the test will fail.

Either way, you end up using the "WhenCalled" part of things to handle your assertion rather than a "Verify" call.

نصائح أخرى

Disclaimer, I work in Typemock.

Since our API is constantly improving, check out another solution for your problem. You can use

Isolate.WhenCalled((<type arg1>, <type arg1>) => fake<method> (<arg1>, <arg2>)).AndArgumentsMatch((<arg1>, <arg2>) => <check>.<behavior>;

for setting your behavior for arguments you want.

Also, don't need to throw any exceptions. Use DoInstead() as shown below to verify, what method wasn't called with exact arguments. No inner assertion is needed.

[TestMethod, Isolated]
public void TestWidget()
{
    Isolate.WhenCalled((int n) => Widget.GetPrice(n)).AndArgumentsMatch((n) => n == 123).WillReturn("A");

    bool wasCalledWith456 = false;

    Isolate.WhenCalled(() => Widget.GetPrice(456)).WithExactArguments().DoInstead((context) =>
    {
        wasCalledWith456 = true;
        context.WillCallOriginal();
        return null;
    });

    Assert.AreEqual("A", Widget.GetPrice(123));
    Widget.GetPrice(234);
    Widget.GetPrice(345);
    Widget.GetPrice(456);

    Assert.IsFalse(wasCalledWith456);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top