-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChangeStreamTest6.cs
More file actions
147 lines (125 loc) · 5.55 KB
/
Copy pathChangeStreamTest6.cs
File metadata and controls
147 lines (125 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using Moq;
using NUnit.Framework;
namespace MongoDBTests
{
// Define interfaces
public interface IUnitOfWork : IDisposable
{
IMongoCollection<BsonDocument> AmpsConfig { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
public interface ISingleValueRepository<T>
{
Task WatchChangesAsync(CancellationToken cancellationToken = default);
}
[TestFixture]
public class AmpsConfigChangeStreamTests
{
private Mock<IUnitOfWork> _unitOfWorkMock;
private Mock<IMongoCollection<BsonDocument>> _ampsConfigCollectionMock;
private Mock<ISingleValueRepository<BsonDocument>> _repositoryMock;
[SetUp]
public void Setup()
{
_unitOfWorkMock = new Mock<IUnitOfWork>();
_ampsConfigCollectionMock = new Mock<IMongoCollection<BsonDocument>>();
_repositoryMock = new Mock<ISingleValueRepository<BsonDocument>>();
// Setup UnitOfWork to return mocked collection
_unitOfWorkMock.Setup(u => u.AmpsConfig).Returns(_ampsConfigCollectionMock.Object);
}
[Test]
public async Task WatchChangesAsync_CallsWatchAsyncOnCollection()
{
// Arrange
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var mockCursor = new Mock<IChangeStreamCursor<ChangeStreamDocument<BsonDocument>>>();
_ampsConfigCollectionMock
.Setup(c => c.WatchAsync(
It.IsAny<PipelineDefinition<ChangeStreamDocument<BsonDocument>, ChangeStreamDocument<BsonDocument>>>(),
It.IsAny<ChangeStreamOptions>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(mockCursor.Object);
var repository = new AmpsConfigRepository(_unitOfWorkMock.Object);
// Act
await repository.WatchChangesAsync(cts.Token);
// Assert
_ampsConfigCollectionMock.Verify(
c => c.WatchAsync(
It.IsAny<PipelineDefinition<ChangeStreamDocument<BsonDocument>, ChangeStreamDocument<BsonDocument>>>(),
It.IsAny<ChangeStreamOptions>(),
cts.Token),
Times.Once());
}
[Test]
public async Task WatchChangesAsync_HandlesInsertOperation()
{
// Arrange
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var mockCursor = new Mock<IChangeStreamCursor<ChangeStreamDocument<BsonDocument>>>();
var changeStreamDocs = new[]
{
new ChangeStreamDocument<BsonDocument>(
operationType: ChangeStreamOperationType.Insert,
fullDocument: new BsonDocument { { "key", "value" } },
ns: new BsonDocument(),
documentKey: new BsonDocument(),
updateDescription: null,
clusterTime: new BsonTimestamp(1),
txnNumber: null,
lsid: null)
};
// Setup cursor behavior
mockCursor.Setup(c => c.MoveNext(cts.Token))
.ReturnsAsync(true)
.Callback(() => cts.Cancel()); // Cancel after first move to prevent infinite loop
mockCursor.Setup(c => c.Current).Returns(changeStreamDocs);
_ampsConfigCollectionMock
.Setup(c => c.WatchAsync(
It.IsAny<PipelineDefinition<ChangeStreamDocument<BsonDocument>, ChangeStreamDocument<BsonDocument>>>(),
It.IsAny<ChangeStreamOptions>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(mockCursor.Object);
var repository = new AmpsConfigRepository(_unitOfWorkMock.Object);
// Act
await repository.WatchChangesAsync(cts.Token);
// Assert
mockCursor.Verify(c => c.MoveNext(cts.Token), Times.Once());
_unitOfWorkMock.Verify(u => u.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Never());
}
[Test]
public void WatchChangesAsync_ThrowsException_WhenCollectionIsNull()
{
// Arrange
_unitOfWorkMock.Setup(u => u.AmpsConfig).Returns((IMongoCollection<BsonDocument>)null);
var repository = new AmpsConfigRepository(_unitOfWorkMock.Object);
// Act & Assert
Assert.ThrowsAsync<ArgumentNullException>(
async () => await repository.WatchChangesAsync());
}
}
// Implementation of the repository
public class AmpsConfigRepository : ISingleValueRepository<BsonDocument>
{
private readonly IUnitOfWork _unitOfWork;
public AmpsConfigRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
}
public async Task WatchChangesAsync(CancellationToken cancellationToken = default)
{
if (_unitOfWork.AmpsConfig == null)
throw new ArgumentNullException(nameof(_unitOfWork.AmpsConfig));
using var cursor = await _unitOfWork.AmpsConfig.WatchAsync(cancellationToken: cancellationToken);
await cursor.ForEachAsync(change =>
{
// Process changes here
Console.WriteLine($"Operation: {change.OperationType}");
}, cancellationToken);
}
}
}