我在 SonarQube 5.3 中发现了一个场景,其中在 Visual Studio 代码覆盖分析的代码覆盖中报告了不同的值。
这是一个使用 MSTest 框架的小型复制品。
我无法确定我们正在做的事情是否有问题,或者其中一个应用程序是否有问题。
被测对象
[Serializable]
public class Document : IEquatable<Document>
{
public long Id { get; set; }
public string Name { get; set; }
public long DocumentHandle { get; set; }
public long BatchId { get; set; }
public string BatchName { get; set; }
public string RepositoryName { get; set; }
public long DocumentTypeId { get; set; }
public string DocumentTypeName { get; set; }
public int SequenceNumber { get; set; }
public string LoanNumber { get; set; }
public bool IsJunked { get; set; }
public DateTime ArrivalDate { get; set; }
public bool Equals(Document other)
{
if (ReferenceEquals(other, null))
{
return false;
}
if (Id != other.Id)
{
return false;
}
if (!string.Equals(Name, other.Name))
{
return false;
}
if (DocumentHandle != other.DocumentHandle)
{
return false;
}
if (BatchId != other.BatchId)
{
return false;
}
if (!string.Equals(BatchName, other.BatchName))
{
return false;
}
if (!string.Equals(RepositoryName, other.RepositoryName))
{
return false;
}
if (DocumentTypeId != other.DocumentTypeId)
{
return false;
}
if (!string.Equals(DocumentTypeName, other.DocumentTypeName))
{
return false;
}
if (SequenceNumber != other.SequenceNumber)
{
return false;
}
if (!string.Equals(LoanNumber, other.LoanNumber))
{
return false;
}
if (IsJunked != other.IsJunked)
{
return false;
}
if (ArrivalDate != other.ArrivalDate)
{
return false;
}
return true;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return Equals((Document) obj);
}
public static bool operator == (Document document1, Document document2)
{
return ReferenceEquals(document1, null) ? ReferenceEquals(document2, null) : document1.Equals(document2);
}
public static bool operator != (Document document1, Document document2)
{
return !(document1 == document2);
}
public override int GetHashCode()
{
// ReSharper disable once BaseObjectGetHashCodeCallInGetHashCode
// This was done to suppress the messages about needing to override GetHashCode
// Because this class has no ReadOnly properties there is no way to provide a better hashcode
return base.GetHashCode();
}
}
该代码具有以下测试:
[TestClass]
[ExcludeFromCodeCoverage]
public class DocumentTests
{
private Document defaultDocument;
private Document alteredDocument;
[TestInitialize]
public void Setup()
{
defaultDocument = new Document
{
Id = 1,
Name = "Growlithe",
DocumentHandle = 2,
BatchId = 3,
BatchName = "Vulpix",
RepositoryName = "Pancham",
DocumentTypeId = 4,
DocumentTypeName = "Skrelp",
SequenceNumber = 5,
LoanNumber = "Zorua",
IsJunked = true,
ArrivalDate = new DateTime(1, 1, 1)
};
alteredDocument = new Document
{
Id = 1,
Name = "Growlithe",
DocumentHandle = 2,
BatchId = 3,
BatchName = "Vulpix",
RepositoryName = "Pancham",
DocumentTypeId = 4,
DocumentTypeName = "Skrelp",
SequenceNumber = 5,
LoanNumber = "Zorua",
IsJunked = true,
ArrivalDate = new DateTime(1, 1, 1)
};
}
[TestMethod]
public void ToStringMethod_DocumentPOCO_ConvertObjectToString()
{
// Arrange
var expectedStringDocument = "Document" + Environment.NewLine +
"\tId: 101" + Environment.NewLine +
"\tName: TestName" + Environment.NewLine +
"\tDocumentHandle: 5000000" + Environment.NewLine +
"\tBatchId: 500000000" + Environment.NewLine +
"\tBatchName: TestBatchName" + Environment.NewLine +
"\tRepositoryName: TestRepositoryName" + Environment.NewLine +
"\tDocumentTypeId: 5000000" + Environment.NewLine +
"\tDocumentTypeName: TestDocumentTypeName" + Environment.NewLine +
"\tSequenceNumber: 101" + Environment.NewLine +
"\tLoanNumber: TestLoanNumber" + Environment.NewLine +
"\tIsJunked: False" + Environment.NewLine +
"\tArrivalDate: " + DateTime.Now + Environment.NewLine;
alteredDocument = new Document
{
Id = 101,
Name = "TestName",
DocumentHandle = 5000000,
BatchId = 500000000,
BatchName = "TestBatchName",
RepositoryName = "TestRepositoryName",
DocumentTypeId = 5000000,
DocumentTypeName = "TestDocumentTypeName",
SequenceNumber = 101,
LoanNumber = "TestLoanNumber",
IsJunked = false,
ArrivalDate = DateTime.Now
};
// Act
var processedDocumentObj = StringUtility.StringUtility.ConvertToString(alteredDocument);
// Assert
Assert.IsTrue(processedDocumentObj.Equals(expectedStringDocument));
}
[TestMethod]
public void EqualsReturnsTrueForEquivalentDocument()
{
Assert.IsTrue(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForNullDocument()
{
alteredDocument = null;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentId()
{
alteredDocument.Id = 9;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentName()
{
alteredDocument.Name = "Arcanine";
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentDocumentHandle()
{
alteredDocument.DocumentHandle = 9;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentBatchId()
{
alteredDocument.BatchId = 9;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentBatchName()
{
alteredDocument.BatchName = "Ninetails";
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentRepositoryName()
{
alteredDocument.RepositoryName = "Pangoro";
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentDocumentTypeId()
{
alteredDocument.DocumentTypeId = 9;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentDocumentTypeName()
{
alteredDocument.DocumentTypeName = "Dragalge";
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentSequenceNumber()
{
alteredDocument.SequenceNumber = 9;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentLoanNumber()
{
alteredDocument.LoanNumber = "Zoroark";
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentIsJunked()
{
alteredDocument.IsJunked = false;
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsReturnsFalseForDifferentArrivalDate()
{
alteredDocument.ArrivalDate = new DateTime(2, 2, 2);
Assert.IsFalse(defaultDocument.Equals(alteredDocument));
}
[TestMethod]
public void EqualsOperatorWorksForNonNullValues()
{
Assert.IsTrue(defaultDocument == alteredDocument);
}
[TestMethod]
public void NotEqualsOperatorWorksForNonNullValues()
{
alteredDocument = null;
Assert.IsTrue(defaultDocument != alteredDocument);
}
[TestMethod]
public void EqualsOperatorReturnsFalseForNullDotNonNull()
{
alteredDocument = null;
Assert.IsFalse(alteredDocument == defaultDocument);
}
[TestMethod]
public void EqualsOperatorReturnsFalseForNonNullDotNull()
{
alteredDocument = null;
Assert.IsFalse(defaultDocument == alteredDocument);
}
[TestMethod]
public void EqualsOperatorReturnsTrueForNullDotNull()
{
alteredDocument = null;
defaultDocument = null;
Assert.IsTrue(defaultDocument == alteredDocument);
}
}
Visual Studio 将百分比显示为:90.10%
SonarQube 显示百分比为:40.00%
Sonar 似乎没有考虑在
if (ReferenceEquals(other, null))
{
return false;
}
方法:public bool Equals(Document other)
我已经调试了测试以验证线路是否被击中。