0

I am testing methods of a class. However, some of them have attributes that do non-related stuff and this make tests fail.

For example, I have this class (in VB.net but could be C# as well)

<AttributeOne()>
<AttributeTwo(Arg1, Arg2)>
Public Overridable Function SomeMethod() As Object
   ' Stuff
End Function

When I call SomeMethod from my mocked object, it will raise some Exceptions because the attributes try to do some stuff that in unit-testing context will not be possible.

[TestFixture]
public class SomeClassUnitTests
{
    [Test]
    public void TestSomeMethod()
    {
        var someClassMock = new Mock<SomeClass>() { CallBase = true };

        //Exception is thrown
        var result = someClassMock.Object.SomeMethod();
    }
}

The tests are written in C#. I am using Moq and Nunit

How can I ignore these attributes when unit-testing?

rafaelc
  • 57,686
  • 15
  • 58
  • 82
  • 1
    You are in violation of the Single Responsibility Principle if this is the case. You are trying to treat the symptom when you should be addressing the cause. – David L Sep 21 '16 at 18:48
  • @HimBromBeere I am testing `SomeMethod`, and this method has some attributes that evaluate global security information (like if user is logged in and stuff). However, in Unit Test there are no such information, so the test fails and I can't get to test the method, got it? – rafaelc Sep 21 '16 at 18:52
  • @DavidL Could you elaborate a little more? – rafaelc Sep 21 '16 at 19:41
  • @RafaelCardoso You cannot ignore the attributes but it appears you can change the attribute value [Remove C# attribute of a property dynamically](http://stackoverflow.com/questions/2483124/remove-c-sharp-attribute-of-a-property-dynamically), maybe you can change the value to something that will allow you to write unit tests. – sly Sep 21 '16 at 21:05
  • 1
    Why are you creating a Mock of `SomeClass` and then calling a method on that mock to test that method? You should only be Mocking `SomeClass` when you want to give it to some *other* class as a dependency, because you are testing the *other* class and want to control the behaviour of the dependencies during the test. In that case, the attributes won't even come into play, because the Mocked `SomeClass` *will not actually be a real SomeClass*. Can you post the exceptions you are getting? – Stephen Byrne Sep 21 '16 at 21:42
  • Don´t mock classes you want to test. Instead mock the *dependencies* of that class. – MakePeaceGreatAgain Sep 22 '16 at 07:41
  • @StephenByrne Because in `SomeClass`, I'll test `SomeMethod`, which calls `SomeOtherMethod` from the same class. I'd like to mock the return of `SomeOtherMethod`, so thats why Im mocking the class with `CallBase = true` got it? – rafaelc Sep 22 '16 at 16:43
  • @HimBromBeere The method calls other methods from the same class – rafaelc Sep 22 '16 at 16:44
  • @RafaelCardoso - I think I see what you mean, does my answer below help? – Stephen Byrne Sep 22 '16 at 18:39

1 Answers1

0

I think I see what you're trying to do here, but it won't work with Mocks, because even if you do create a Mock SomeClass, you also have to mock the SomeMethod function - you can't use the real one!

That means that you are not testing it, just testing the mocked version of it.

However, why not try this without Mocks?

You can make SomeOtherMethod virtual, and then subclass SomeClass just for this test. You then write whatever override of the SomeOtherMethod function you like; when you call the real SomeClass.SomeMethod, it will call into that overridden version.

i.e. (sorry, doing this in C# as my VB is rusty) suppose SomeClass looks like this, picking a deliberately useless functionality so as not to confuse:

public class SomeClass
{
    public virtual int SomeMethod()
    {
      return SomeOtherMethod() / 2;
    }

    protected virtual SomeOtherMethod()
    {
        return [some crazy maths]
    }
}

You want to test that SomeMethod correctly returns half of what SomeOtherMethod does.

So now you can do this, in the test project:

public class SomeClassTestDouble: SomeClass
{
    protected override int SomeOtherMethod()
    {
         return 2;
    }
}

then in your test:

var sut = new SomeClassTestDouble();
var expected = 1;
var actual = sut.SomeMethod();
Assert.Equal(expected, actual)

Now you have tested that SomeMethod works as expected without any Mocking. Indeed many would argue that, unless you are crossing an architectural or system boundary, you prefer test doubles (which includes stubs) over Mocks. I'm not going to say if I agree or not in general, but in this case I think it's better not to Mock.

Note on the Attributes

Bear in mind re. the Attributes - they should not do anything at all until some other part of the system tells them to do something. If that part of the system is not running (i.e during tests) then these attributes should be totally inert. If they are not, then I'd tend to look at your Unit Test project and make sure you're not accidentally running "live" stuff like runtime security frameworks or something

Community
  • 1
  • 1
Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51