简体   繁体   中英

How to mock class members in C#?

I'm trying to use FakeItEasy to mock an object that is a member of a C# class I'm creating.

The FakeItEasy documentation indicates that you fake an object in a way similar to this:

private static var m_physics = A.Fake<IPhysics>();

That is, using the "var" keyword.

However, in this case the C# compiler doesn't like the fact that var is being used in a non-local context. I get this error:

The contextual keyword 'var' may only appear within a local variable declaration

Can't I mock an object that's not local?

I think you're missing the point of mocks/stubs. Mocks and stubs are used for testing when you don't want the subject under test to pass or fail depending on other components that it depends on. So what you do is swap explicit implementations of these out for mocks/stubs of these dependencies that you can completely control within the test.

class Foo {
    public Foo(IBar bar) { }
    public object M() { // do something with IBar }
}

Here Foo has a dependency on IBar . We want to test Foo.M . We don't want the test to pass or fail based on whether or not the concrete implementation that we give to Foo of IBar is working or not.

[Fact]
public void MDoesWhatItIsSupposeToDo() {
    var foo = new Foo(new Bar());
    object expected = // expected result
    Assert.Equal(expected, foo.M());
}

If Bar is broken this test could fail even though Foo might be coded perfectly correctly. So you sub in a mock/stub to preven this

[Fact]
public void MDoesWhatItIsSupposeToDo() {
    var bar = A.Fake<IBar>();
    // set up bar to do what is expected of IBars
    var foo = new Foo(bar);
    object expected = // expected result
    Assert.Equal(expected, foo.M());
}

Now this test only passes or fails if Foo is coded correctly or not, independently of whether or not your concrete implementations of IBar are correct.

This is the point of mocks.

So all of this is to say, you are not using mocks properly.

Can't I mock an object that's not local?

You can, but not in the way that you are doing. First, fields can't be implicitly typed. Secondly, you don't mock the field explicitly like you've done. Instead you do it like this:

class Whatever {
    private IPhysics m_physics;

    public Whatever(IPhsyics physics) { this.m_physics = physics; }
}

Then:

var physics = A.Fake<IPhysics>();
var whatever = new Whatever(physics);

You can only use the 'var' keyword in a local context like a function block. You cannot declare a class member as a 'var'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM