diff --git a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
index 32f90d5cbf..c4c1f49346 100644
--- a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
+++ b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
@@ -14,6 +14,7 @@
+
diff --git a/tests/Avalonia.Base.UnitTests/Logging/LoggingTests.cs b/tests/Avalonia.Base.UnitTests/Logging/LoggingTests.cs
new file mode 100644
index 0000000000..193d5e3a45
--- /dev/null
+++ b/tests/Avalonia.Base.UnitTests/Logging/LoggingTests.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Avalonia.Controls;
+using Avalonia.Controls.Shapes;
+using Avalonia.Logging;
+using Avalonia.Markup.Xaml;
+using Avalonia.UnitTests;
+using Avalonia.Utilities;
+using Xunit;
+
+namespace Avalonia.Base.UnitTests.Logging
+{
+ public class LoggingTests
+ {
+ [Fact]
+ public void Control_Should_Not_Log_Binding_Errors_When_Detached_From_Visual_Tree()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ using var logSink = new StubLogSink(LogEventLevel.Warning);
+ var panel = window.FindControl("panel");
+ var rect = window.FindControl("rect");
+ window.ApplyTemplate();
+ window.Presenter.ApplyTemplate();
+ panel.Children.Remove(rect);
+ Assert.Equal(0, logSink.Results.Count);
+ }
+ }
+ }
+
+ class StubLogSink : ILogSink, IDisposable
+ {
+ LogEventLevel _level;
+ public StubLogSink(LogEventLevel level)
+ {
+ _level = level;
+ Logger.Sink = this;
+ }
+ public void Dispose()
+ {
+ Logger.Sink = null;
+ }
+ public List Results { get; set; } = new List();
+
+ public bool IsEnabled(LogEventLevel level, string area)
+ {
+ return true;
+ }
+
+ public void Log(LogEventLevel level, string area, object source, string messageTemplate)
+ {
+ if (level >= _level)
+ {
+ Results.Add(Format