views:

304

answers:

1

Hi all - I'm learning TDD and the MVP pattern. I've created a simple WinForms app that's like a replacement for the TOAD SQL tool. I'm trying to go back and write tests now for the code I've already written (which I know isn't the correct process for TDD, but please bear with me). In my test class for the form, I want to test the concrete Presenter, but mock out the WinForm as the presenter has real logic in it that should be tested. However, when I mock the view using Moq, I'm not seeing expected results. In the code below, the first 2 tests PASS, but the 3rd FAILS on the first Assert. When I attach the debugger to NUnit and run, the Environment property isn't set to Environments.Test when presenter.IsDangerousSQL is called:

private Mock<IQueryForm> mockWindow;
    private QueryFormPresenter presenter;

    /// <summary>
    /// Runs ONCE prior to any tests running
    /// </summary>
    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {
        //We're interested in testing the QueryFormPresenter class here, but we 
        //don't really care about the QueryForm window (view) since there is hardly any code in it.
        //Therefore, we create a mock of the QueryForm view, and pass it to the QueryFormPresenter to use.
        mockWindow = new Mock<IQueryForm>();
        presenter = new QueryFormPresenter(mockWindow.Object);
    }

    [Test]
    public void User_Can_Execute_Selects_From_Any_Environment()
    {
        Assert.AreEqual(false, presenter.IsDangerousSQL("select 1"));
    }

    [Test]
    public void User_Cant_Execute_Schema_SQL_On_Any_Environment()
    {
        Assert.AreEqual(true, presenter.IsDangerousSQL("alter table"));
        Assert.AreEqual(true, presenter.IsDangerousSQL("DrOp table"));
    }

    //Updates, Deletes and Selects are allowed in Test, but not in Production
    [Test]
    public void User_Can_Only_Execute_Updates_Or_Deletes_Against_Test()
    {
        //mockWindow.SetupSet(w => w.Environment = Environments.Test);
        mockWindow.Object.Environment = Environments.Test;
        Assert.AreEqual(false, presenter.IsDangerousSQL("update "));
        Assert.AreEqual(false, presenter.IsDangerousSQL("delete "));

        //mockWindow.SetupSet(w => w.Environment = Environments.Production);
        //mockWindow.Object.Environment = Environments.Test;
        Assert.AreEqual(true, presenter.IsDangerousSQL("update "));
        Assert.AreEqual(true, presenter.IsDangerousSQL("delete "));
    }

I greatly appreciate any insights anyone can offer! And also, should the IsDangerousSQL method actually be in a Model class since it represents business logic rather than directly reacting to a user action?

Thanks!!

Andy

A: 

Assuming your code under test is checking the Environment property you'd want to use SetupGet instead of SetupSet (i.e. tell the mock what to return when its environment property is called)

mockWindow.SetupGet(s => s.Environment).Returns(Environments.Test);

This because you're not setting the property in the code you're getting it.

Alternatively if you'd like to treat the Environment property as a standard property, which is what you're doing when you write statements like

mockWindow.Object.Environment = Environments.Test;

You can use

mockWindow.SetupProperty(qf => qf.Environment);

Personally I prefer the first approach.

sighohwell
Thank you very much!! The 2nd approach doesn't work though if I combine the mockWindow.Object.Environment = Environments.Test; with the mockWindow.SetupProperty(qf => qf.Environment);. I agree though that the 1st approach is the way to go. Thanks!!
Andy