I am using the pipes and filters pattern as described in this blog post.
I am wondering how to test this effectively. My idea was to just test each filter independently. For example I have a filter that looks like this
func watchTemperature(ctx context.Context, inStream <-chan int) {
maxTemp = 90
go func() {
for {
select {
case <-ctx.Done():
return
case temp := <-inStream:
if temp > maxTemp{
log.Print("Temperature too high!")
}
}
}
}()
}
In my test for now I only want to see if the log has been printed. My test looks as follows.
func TestWatchTemperature(t *testing.T) {
maxTemp = 90
ctx := context.Background()
inStream := make(chan int)
defer close(inStream)
watchTemperature(ctx, inStream)
var buf bytes.Buffer
log.SetOutput(&buf)
inStream<-maxTemp+1
logMsg := buf.String()
assert.True(t, strings.Contains(logMsg, "Temperature too high!"),
"Expected log message not found")
}
As this filter is the end of my pipeline, I do not have an out channel I can read from to determine if this goroutine/filter has already done something.
The only thing I found online so far was, to just wait for a few seconds after writing to the inStream in my test and then check the log. However this seems like a really poor choice, as it simple introduces a race condition and slows down the test.
What is the best way to test something like this or is there simply no good way to test it with this design of my filter and I always need an outStream?