0

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?

Buggieboy
  • 4,636
  • 4
  • 55
  • 79
  • 3
    I think you are confusing mocking with implicit typing. If you change your `var` to the actual type returned, you shouldn't have a problem. – Tejs May 11 '11 at 17:12
  • mocking class members is so not nice... – pixelbobby May 11 '11 at 17:12
  • The type doesn't exist yet. Hence, the need for the mock. – Buggieboy May 11 '11 at 17:15
  • Isn't the return type an IPhysics, so rather than use 'var' you'd just use IPhysics as the type of m_physics? – rusty May 11 '11 at 17:29
  • @_rusty: While that's correct, it misses the point of injecting dependencies and mocking. – jason May 11 '11 at 17:40
  • @Jason: Clearly this isn't something you'd ever want to do :) Just answering the question of what to do about the compiler not liking 'var' here. – rusty May 11 '11 at 17:44
  • @_rusty: But see, the point is that changing `var` to `IPhysics` doesn't change the fact that mocks are being used incorrectly. That is the heart of the confusion behind this question. So changing `var` to `IPhysics` gets rid of a compiler error, but it doesn't get rid of a more fundamental conceptual error. – jason May 11 '11 at 18:41
  • @Jason: You've hit the nail on the head. My question arose out of a conflation of what mocks should be used for. As I mention below, they are overkill for this purpose. I really just need to be coding to an interface. – Buggieboy May 11 '11 at 18:49

2 Answers2

6

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);
jason
  • 236,483
  • 35
  • 423
  • 525
  • Okay, this is a good summary. Thanks. It's not so much that I was missing the point of mocks, as that I wanted to use an existing mechanism (mocks) to be able to compile class A, when A contains an instance of B, and B has not yet been implemented. The last bit that you include above seems to give me a way of doing that. – Buggieboy May 11 '11 at 17:40
  • 1
    @Buggieboy: But that's why you code against interfaces (`IPhysics`) instead of concrete implementations. That question has nothing to do with mocking. – jason May 11 '11 at 18:08
  • yeah that's what I now understand. Using a mocking framework was overkill for what I was doing. Plain old interfaces are quite adequate. – Buggieboy May 11 '11 at 18:46
0

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

Kelly Summerlin
  • 651
  • 4
  • 10
  • Right. That is what the error message says. That is what led to the question of how to use the mocking framework given this restriction. – Buggieboy May 11 '11 at 17:29