Welcome to Typemock Answers. Here you can ask and receive answers from other community members. And if you liked or disliked an answer or thread: react with an up- or downvote Enjoy!

How to mock ConfigurationManager.AppSettings.Get

+2 votes
Hi everyone,

I'm new to mocking and would like some help. I've got a number of unit tests working with various mocks and even got my build server (teamcity) running the tests successfully. But there is one test that is giving me problems. How can I mock the following:

string url = ConfigurationManager.AppSettings.Get("homeUrl");


In my test I've tried a number of things like this:

AppSettingsSection appSettings = new AppSettingsSection();
appSettings.Settings.Add("homeUrl", "http://www.domain.com");

Mock configurationManagerMock = MockManager.MockAll(typeof(ConfigurationManager));
configurationManagerMock.ExpectAndReturn("AppSettings", appSettings);


When I run this unit test, I get the following error:

No method AppSettings in type System.Configuration.ConfigurationManager


I'm running VS2008 targeting .NET 2.0. I'm using the built-in test projects supplied by VS2008.

Any help would be great. Thanks in advance.

Andy
asked Apr 11, 2008 by andy.pike (580 points)

8 Answers

+2 votes
I've just noticed that I was looking at the wrong version on the .NET documentation. For 2.0, the AppSettings static property is actually a NameValueCollection:

http://msdn2.microsoft.com/en-us/librar ... ings(VS.80).aspx

So, changing my test to this:

NameValueCollection appSettings = new NameValueCollection();
appSettings.Add("homeUrl", "http://www.domain.com");

Mock configurationManagerMock = MockManager.MockAll(typeof(ConfigurationManager));
configurationManagerMock.ExpectAndReturn("AppSettings", appSettings);


still gives me the same error. Any ideas?
answered Apr 11, 2008 by andy.pike (580 points)
+1 vote
Hi,

I actually remember there was something different with this type. :?

Anyway, I think that the API you are looking or is ExpectGet, for properties.
Take a look at: http://typemock.com/Docs/HowTo.html for examples.

Let me know how it works out.
answered Apr 11, 2008 by gilz (20,200 points)
+2 votes
OK, thanks. That has fixed the error but the test is still failing. This is because the call to ConfigurationManager.AppSettings is returning an empty NameValueCollection object (not null, just not items) even though I have passed in a new NameValueCollection with a valid item to ExpectGet.

Any ideas?
answered Apr 11, 2008 by andy.pike (580 points)
+2 votes
Right, something strange is going on. If I use the "Run all tests in solution" function of VS2008, the test passes! But if I use the "Run tests in current context" just this test runs and it fails for the reasons detailed above. Have I found a bug?

When all tests are run, only one test is executed before this one and it doesn't use the AppSettings object at all.

Thoughts?
answered Apr 11, 2008 by andy.pike (580 points)
+1 vote
Hi,

I'm not sure it's a bug YET, but VS2008 continues to throw some curve balls at us. What you describe could point to an issue with a static constructor, or maybe something that you do/don't clear in a setup / tear down functions.

I would like to take a look at your code, if you can reproduce it in a separate solution. I'll send a separate mail instructions.
answered Apr 11, 2008 by gilz (20,200 points)
+1 vote
Something I noticed that might be giving you trouble: ConfigurationManager.AppSettings is a static property, so you need to use mock.CallStatic.ExpectGet, not just mock.ExpectGet.

I created this test and it works:
[Test]
public void MockAppSettings()
{
  Mock configurationManagerMock = MockManager.Mock(typeof(ConfigurationManager));
  NameValueCollection customSettings = new NameValueCollection();
  customSettings.Add("homeUrl", "http://www.domain.com");
  configurationManagerMock.CallStatic.ExpectGet("AppSettings", customSettings);
   
  string result = ConfigurationManager.AppSettings.Get("homeUrl");
  Assert.AreEqual("http://www.domain.com", result);
}


Of course, it's far easier to do this with Natural mocks and call chaining:

[Test]
public void CallChaining()
{
  using(RecordExpectations recorder = RecorderManager.StartRecording())
  {
    string dummy = ConfigurationManager.AppSettings.Get("homeUrl");
    recorder.Return("http://www.domain.com");
  }
   
  string result = ConfigurationManager.AppSettings.Get("homeUrl");
  Assert.AreEqual("http://www.domain.com", result);
}
answered Apr 11, 2008 by tillig (6,430 points)
+2 votes
Thanks for the update. I tried adding CallStatic, but that had no effect.

I'll try to create a sample that I can send you guys for testing. The build server runs the tests just fine, it's only failing in VS2008 when I hit the "Run tests in current context" option. Everything else is working perfectly and I really like TypeMock, good work!

Thanks
answered Apr 11, 2008 by andy.pike (580 points)
+1 vote
Hi,

Since I'm joining late into a thread i might be repeating some stuff. but anyway here are examples on how to mock the statement in your original post:
string url = ConfigurationManager.AppSettings.Get("homeUrl");


Natrual Syntx (which is much simpler as Travis already mentioned):
[Test]
[VerifyMocks]
public void Test()
{
    using (RecordExpectations rec = new RecordExpectations())
    {
        string dummy = ConfigurationManager.AppSettings.Get("homeUrl");
        rec.Return("DummyUrl");
    }

    string url = ConfigurationManager.AppSettings.Get("homeUrl");
    Assert.AreEqual("DummyUrl", url);
}


and refelctive syntax:
[Test]
[VerifyMocks]
public void test_reflective()
{
    MockObject mockCollection = MockManager.MockObject<NameValueCollection>();
    mockCollection.ExpectAndReturn("Get", "DummyUrl");

    Mock confManagermock = MockManager.Mock(typeof(ConfigurationManager));
    confManagermock.ExpectGet("AppSettings", mockCollection.Object);

    string url = ConfigurationManager.AppSettings.Get("homeUrl");
    Assert.AreEqual("DummyUrl", url);
}


Hope this helps
answered Apr 13, 2008 by lior (18,340 points)
...