开发者

What is the simplest unit test to implement for asserting a particular method is called?

I have one class and I want to implement a unit test in one of its public methods to test if a specific method is called.

To simplify it, let's take the class and the unit test开发者_如何学JAVA below.

What should I change or implement (like an interface etc.) so that I can assert "MakeNoise method calls Bark method"

I can use RhinoMocks if necessery.

public class Animal
{
    public string AnimalType {get; set;}
    public string Bark()
    {
        if(AnimalType=="dog")
        {
            return "Hof! Hof! Hof!";
        }

        return string.Empty;
    }

    public string MakeNoise()
    {
        if(AnimalType=="dog")
        {
            return Bark();
        }

        return 
            string.Empty;

    }
}

[TestMethod]
public void MakeNoise_WithAnimalTypeDog_CallsBarkMethod()
{

    var dog = new Animal(){AnimalType="dog"};
    dog.MakeNoise();

    // How can I test if the MakeNoise method called BarkMethod ?

}


This is what you're interested in, the output. Test the output.

var expected = "Hof! Hof! Hof!";
var actual = dog.MakeNoise();
Assert.AreEqual(actual, expected);

If the method is inside the class under test, it's an implementation detail. Where you might want to test interactions is if your class has a collaborator, and you want to your tests of Animal to be isolated from the collaborator (perhaps Bar). Then you might elect to use a fake of Bar to ensure Animal acts appropriately (and, of course, you'd have the appropriate tests in place for the real Bar). If this is closer to your real question, please update it.

With that said, your class hierarchy (if this is indeed an indication) could use some work. Animal should not have a method that is relevant only to a dog. You should not be type checking (class, enum, whatever) in the class. Create a Dog that inherits from Animal, have it appropriately override the MakeNoise method.

class Animal
{
    public virtual string MakeNoise() { return whatever; }
}

class Dog : Animal 
{
    public override string MakeNoise() { return "Hof! Hof! Hof!"; }
}

//
Animal dog = new Dog();
var noise = dog.MakeNoise();

You may even go so far as to make Animal abstract.


You should never check if a certain method calls another method. The actual implementation should never be interesting.

imho proper unit testing should be "black box" testing. You should not know what kind of logic a method consists of. You should only know that kind of result it delivers and what kind of exceptions it can throw (and under what conditions). And those specified cases are the ones you should test.


Although I agree with @jgauffin a unit test should not actually behave like that, there's a dirty way to do it regardless.

First, define your Bark method virtual. Then, override it in an inheriting class which is part of your test suite.

public class AnimalTestClass : Animal
{
     public bool BarkCalled{get;set;}

     public override string Bark()
     {
          BarkCalled = true;
          return base.Bark();
     }
}

Then, in your test method, instantiate this class

 [TestMethod]
 public void MakeNoise_WithAnimalTypeDog_CallsBarkMethod()
 {

     var dog = new AnimalTestClass(){AnimalType="dog"};
     dog.MakeNoise();

     // How can I test if the MakeNoise method called BarkMethod ?
     Assert.IsTrue(dog.BarkCalled);
 }

Edit: Fixed a code typo (forgot to call base.Bark())

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜