2016-09-02 15 views
-1

を指定しているだけ最後の値を返すのはなぜDAOクラスでのIDbConnectionを模擬しようとしていますが、私は次のエラー受け付けております:NSubstituteは倍数が

文字列の長さを両方5.文字列が予想されるインデックス0 で異なるされています: "11111" しかしだった。ここでは "22222"

が私のコードです:テスト

クラス enter image description here

私はどちらも同じですMeterSNフィールド、のを除いて期待どおり私のすべてが設定されている。ここで

internal class ImportAcquisitionDataDAO : IImportAcquisitionDataDAO 
{ 
    private static Logger log = LogManager.GetCurrentClassLogger(); 

    private readonly IDbConnection connection; 

    internal ImportAcquisitionDataDAO(IDbConnection connection) 
    { 
     this.connection = connection; 
    } 

    internal List<DefinitionEntry> GetDefinitions() 
    { 
     log.Debug("Getting definitions from database."); 

     var definitions = new List<DefinitionEntry>(); 

     using (connection) 
     { 
      connection.Open(); 
      log.Trace("Database connection opened"); 

      IDbCommand command = connection.CreateCommand(); 
      command.CommandText = @"SELECT * 
            FROM MAPPING"; 

      IDataReader reader = command.ExecuteReader(); 
      log.Trace("Command executed:\n{0}", command.CommandText); 

      definitions = GetMeterEntries(reader); 
     } 

     log.Debug("Obtained {0} definitions.", definitions.Count); 
     return definitions;   
    } 

    private List<DefinitionEntry> GetMeterEntries(IDataReader reader) 
    { 
     log.Trace("Parsing definitions from response"); 

     var result = new List<DefinitionEntry>(); 

     while (reader.Read()) 
     { 
      var definition = new DefinitionEntry(
       reader.GetString(0), 
       reader.GetString(1), 
       reader.GetString(2), 
       reader.IsDBNull(3) ? null : reader.GetString(3), 
       reader.IsDBNull(4) ? null : reader.GetString(4), 
       reader.IsDBNull(5) ? null : reader.GetString(5), 
       reader.IsDBNull(6) ? null : reader.GetString(6) 
       ); 

      log.Trace(definition.ToString()); 
      result.Add(definition); 
     } 

     return result; 
    } 
} 

public class DefinitionEntry 
{ 
    public string MeterSN { get; private set; } 
    public string MATNR { get; private set; } 
    public string IpAddress { get; private set; } 
    public string SIM { get; private set; } 
    public string ModulID { get; private set; } 
    public string SIMUser { get; private set; } 
    public string SIMPassword { get; private set; } 

    public DefinitionEntry(string meterSN, string matnr, string ipAddress, string sim, string modulId, string simUser, string simPassword) 
    { 
     MeterSN = meterSN; 
     MATNR = matnr; 
     IpAddress = ipAddress; 
     SIM = sim; 
     ModulID = modulId; 
     SIMUser = simUser; 
     SIMPassword = simPassword; 
    } 
} 

Testクラス

[TestFixture] 
public class ImportAcquisitionDataDAOTests 
{ 
    private IDbConnection mockConnection; 
    private IDbCommand mockCommand; 
    private IDataReader mockReader; 
    private ImportAcquisitionDataDAO dao; 

    [SetUp] 
    public void SetUp() 
    { 
     mockConnection = Substitute.For<IDbConnection>(); 
     mockCommand = Substitute.For<IDbCommand>(); 
     mockReader = Substitute.For<IDataReader>(); 
     dao = new ImportAcquisitionDataDAO(mockConnection); 

     mockConnection.CreateCommand().Returns(mockCommand); 
     mockCommand.ExecuteReader().Returns(mockReader); 
    } 

    [Test] 
    public void TestGetDefinitions() 
    { 
     // mock 
     var databaseDefinitionFirst = new DefinitionEntry("11111", "AS3000-5/100-400-P", "10.42.42.26", "SIM-001", "12345lkj", "alibaba", "abrakadabra"); 
     var databaseDefinitionSecond = new DefinitionEntry("22222", "AS3000-5/100-400-Q", "10.42.42.158", null, null, null, null); 

     mockReader.Read().Returns(true, true, false); 
     mockReader.GetString(Arg.Is<int>(0)).Returns(databaseDefinitionFirst.MeterSN, databaseDefinitionSecond.MeterSN); 
     mockReader.GetString(Arg.Is<int>(1)).Returns(databaseDefinitionFirst.MATNR, databaseDefinitionSecond.MATNR); 
     mockReader.GetString(Arg.Is<int>(2)).Returns(databaseDefinitionFirst.IpAddress, databaseDefinitionSecond.IpAddress); 
     mockReader.IsDBNull(Arg.Is<int>(3)).Returns(false, true); 
     mockReader.GetString(Arg.Is<int>(3)).Returns(databaseDefinitionFirst.SIM); 
     mockReader.IsDBNull(Arg.Is<int>(4)).Returns(false, true); 
     mockReader.GetString(Arg.Is<int>(4)).Returns(databaseDefinitionFirst.ModulID); 
     mockReader.IsDBNull(Arg.Is<int>(5)).Returns(false, true); 
     mockReader.GetString(Arg.Is<int>(5)).Returns(databaseDefinitionFirst.SIMUser); 
     mockReader.IsDBNull(Arg.Is<int>(6)).Returns(false, true); 
     mockReader.GetString(Arg.Is<int>(6)).Returns(databaseDefinitionFirst.SIMPassword); 

     // use 
     List<DefinitionEntry> tested = dao.GetDefinitions(); 

     // verify 
     Assert.AreEqual(2, tested.Count); 
     AssertDefinitionEntry(databaseDefinitionFirst, tested.First()); 
     AssertDefinitionEntry(databaseDefinitionSecond, tested.Last()); 
    } 

    private void AssertDefinitionEntry(DefinitionEntry expected, DefinitionEntry tested) 
    { 
     Assert.AreEqual(expected.MeterSN, tested.MeterSN); 
     Assert.AreEqual(expected.MATNR, tested.MATNR); 
     Assert.AreEqual(expected.IpAddress, tested.IpAddress); 
     Assert.AreEqual(expected.SIM, tested.SIM); 
     Assert.AreEqual(expected.ModulID, tested.ModulID); 
     Assert.AreEqual(expected.SIMUser, tested.SIMUser); 
     Assert.AreEqual(expected.SIMPassword, tested.SIMPassword); 
    } 
} 

そしては、最初のアサートが実行される前にデバッグ画面ですエントリ。しかし、私は理由を見つけることができません

+0

可能な限り簡潔に提供してください。あなたは答えを得る可能性がより高くなります。 –

+0

ありがとうございます。私はコードができるだけ簡潔であることに同意しますが、一方で誰もが同じコードの振る舞いを再現できるように、コードを「完全」にしておきたいと思いました。私はいくつかの行を取るロギングを削除することができますが、私の視点からは長いコードですが、複雑なロジックはなく、その意味を理解するのは簡単です。 – ceezy

答えて

0

これは非常に微妙な問題です。

短い答え:最後の呼び出し可能にする

移動mockReader.GetString(Arg.Is<int>(0)).Returns(databaseDefinitionFirst.MeterSN, databaseDefinitionSecond.MeterSN);は(ちょうどmockReader.GetString(Arg.Is<int>(6))下)スタブ。

長い答え:

我々はmockReader.GetString(Arg.Is<int>(5))を言う

Arg.Is部分はゼロを返し、 mockReader.GetString(0)を意味し、テスト・セットアップの中に複数回呼び出されます。したがって、 "11111"が最初に返されますが、 GetDefinitionsが呼び出されるまでに、その値はすでに使用されています。


ちなみに、NSubstituteはあなたのコードを少し簡略化されますmockReader.GetString(Arg.Is<int>(5))と同じmockReader.GetString(5).Returns(...)を扱います。

別の脇に、私はuse a real data reader in your testsへの道を見つけることを試みることを提案するでしょう。次のような何かが、あなたがそのタイプの詳細をからかっ避ける聞かせ:

 DataTable dt = new DataTable(); 
     dt.Columns.AddRange(
      new [] { 
       new DataColumn("a", typeof(string)), 
       new DataColumn("b", typeof(string)), 
       new DataColumn("c", typeof(string)), 
       new DataColumn("d", typeof(string)), 
       new DataColumn("e", typeof(string)), 
       new DataColumn("f", typeof(string)), 
       new DataColumn("g", typeof(string)) 
      }); 
     dt.Rows.Add("11111", "AS3000-5/100-400-P", "10.42.42.26", "SIM-001", "12345lkj", "alibaba", "abrakadabra"); 
     dt.Rows.Add("22222", "AS3000-5/100-400-Q", "10.42.42.158", null, null, null, null); 
     mockReader = new DataTableReader(dt); 

次に、あなたがあなたのテストからすべてのモック設定を削除することができます。 (例えば、databaseDefinitionFirstのような期待されるオブジェクトを与えられた読者に自動的に読者を投入するようないくつかのヘルパーメソッド)を調整することで、すべてのコードをすべて偽造するのではなく、読者とやり取りするすべてのコードをテストする良い方法になります。時間。

+0

お返事ありがとうございました。私は変更を加え、今テストパスをしました。記事は私のために啓発していた。 – ceezy