rhino-mocksarrange-act-assert

RhinoMocks AAA Syntax


I've spent a good part of the day trying to figure out why a simple RhinoMocks test doesn't return the value I'm setting in the return. I'm sure that I'm just missing something really simple but I can't figure it out. Here's my test:

    [TestMethod]
    public void CopyvRAFiles_ShouldCallCopyvRAFiles_ShouldReturnTrue2()
    {
        FileInfo fi = new FileInfo(@"c:\Myprogram.txt");
        FileInfo[] myFileInfo = new FileInfo[2];
        myFileInfo[0] = fi;
        myFileInfo[1] = fi;
        var mockSystemIO = MockRepository.GenerateMock<ISystemIO>();
        mockSystemIO.Stub(x => x.GetFilesForCopy("c:")).Return(myFileInfo);
        mockSystemIO.Expect(y => y.FileCopyDateCheck(@"c:\Myprogram.txt", @"c:\Myprogram.txt")).Return("Test");
        CopyFiles copy = new CopyFiles(mockSystemIO);

        List<string> retValue = copy.CopyvRAFiles("c:", "c:", new AdminWindowViewModel(vRASharedData));
        mockSystemIO.VerifyAllExpectations();
    }

I have an interface for my SystemIO class I'm passing in a mock for that to my CopyFiles class. I'm setting an expectation on my FileCopyDatCheck method and saying that it should Return("Test"). When I step through the code, it returns a null insteaed. Any ideas what I'm missing here?

Here's my CopyFiles class Method:

    public List<string> CopyvRAFiles(string currentDirectoryPath, string destPath, AdminWindowViewModel adminWindowViewModel)
    {
        string fileCopied;
        List<string> filesCopied = new List<string>();
        try
        {
            sysIO.CreateDirectoryIfNotExist(destPath);

            FileInfo[] files = sysIO.GetFilesForCopy(currentDirectoryPath);

            if (files != null)
            {
                foreach (FileInfo file in files)
                {
                    fileCopied = sysIO.FileCopyDateCheck(file.FullName, destPath + file.Name);
                    filesCopied.Add(fileCopied);
                }
            }

            //adminWindowViewModel.CheckFilesThatRequireSystemUpdate(filesCopied);

            return filesCopied;
        }
        catch (Exception ex)
        {
            ExceptionPolicy.HandleException(ex, "vRAClientPolicy");
            Console.WriteLine("{0} Exception caught.", ex);

            ShowErrorMessageDialog(ex);
            return null;
        }
    }

I would think that "fileCopied" would have the Return value set by the Expect. The GetFilesForCopy returns the two files in myFileInfo. Please Help. :)

thanks in advance!


Solution

  • A mock will not start returning recorded answers until it is switched to replay mode with Replay(). Stubs and mocks do no work in the same way. I have written a blog post about the difference.

    Also note that you are mixing the old record-replay-verify syntax with the new arrange-act-assert syntax. With AAA, you should not use mocks and Expect. Instead, use stubs and AssertWasCalled like this:

    [TestMethod]
    public void CopyvRAFiles_ShouldCallCopyvRAFiles_ShouldReturnTrue2()
    {
        // arrange
        FileInfo fi = new FileInfo(@"c:\Myprogram.txt");
        FileInfo[] myFileInfo = new FileInfo[2];
        myFileInfo[0] = fi;
        myFileInfo[1] = fi;
    
        var stubSystemIO = MockRepository.GenerateStub<ISystemIO>();
        stubSystemIO.Stub(
            x => x.GetFilesForCopy(Arg<string>.Is.Anything)).Return(myFileInfo);
        stubSystemIO.Stub(
            y => y.FileCopyDateCheck(
                Arg<string>.Is.Anything, Arg<string>.Is.Anything)).Return("Test");
    
        CopyFiles copy = new CopyFiles(mockSystemIO);
    
        // act
        List<string> retValue = copy.CopyvRAFiles(
            "c:", "c:", new AdminWindowViewModel(vRASharedData));
    
        // make assertions here about return values, state of objects, stub usage
        stubSystemIO.AssertWasCalled(
            y => y.FileCopyDateCheck(@"c:\Myprogram.txt", @"c:\Myprogram.txt"));
    }
    

    Note how setting up the behavior of stubs at the start is separate from the assertions at the end. Stub does not set any expectations.

    The advantage of seperating behavior and assertions is that you can make less assertions per test, making it easier to diagnose why a test failed.